package com.zenithmind.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.chat.mapper.ChatGroupMemberMapper;
import com.zenithmind.chat.pojo.entity.ChatGroupMember;
import com.zenithmind.chat.pojo.vo.ChatUserVO;
import com.zenithmind.chat.service.ChatGroupMemberService;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.utils.BeanCopyUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 群组成员服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatGroupMemberServiceImpl extends ServiceImpl<ChatGroupMemberMapper, ChatGroupMember> 
        implements ChatGroupMemberService {

    @Override
    public PageResult<ChatUserVO> getGroupMemberPage(String groupId, Integer status, Integer role, String keyword,
                                                     Integer pageNum, Integer pageSize) {
        Page<ChatGroupMember> page = new Page<>(pageNum, pageSize);
        
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(status != null, ChatGroupMember::getStatus, status)
               .eq(role != null, ChatGroupMember::getRole, role)
               .like(StringUtils.hasText(keyword), ChatGroupMember::getUserName, keyword)
               .orderByAsc(ChatGroupMember::getRole)
               .orderByDesc(ChatGroupMember::getJoinTime);
        
        IPage<ChatGroupMember> result = page(page, wrapper);
        
        List<ChatUserVO> voList = result.getRecords().stream()
            .map(this::convertToUserVO)
            .collect(Collectors.toList());
        
        return PageResult.of(voList, result.getTotal());
    }

    @Override
    public List<ChatUserVO> getGroupMembers(String groupId, Integer status) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(status != null, ChatGroupMember::getStatus, status)
               .orderByAsc(ChatGroupMember::getRole)
               .orderByDesc(ChatGroupMember::getJoinTime);
        
        List<ChatGroupMember> members = list(wrapper);
        
        return members.stream()
            .map(this::convertToUserVO)
            .collect(Collectors.toList());
    }

    @Override
    public List<ChatUserVO> getGroupAdmins(String groupId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getStatus, 1)
               .in(ChatGroupMember::getRole, 1, 2) // 群主和管理员
               .orderByAsc(ChatGroupMember::getRole);
        
        List<ChatGroupMember> admins = list(wrapper);
        
        return admins.stream()
            .map(this::convertToUserVO)
            .collect(Collectors.toList());
    }

    @Override
    public ChatUserVO getGroupMemberInfo(String groupId, String userId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember member = getOne(wrapper);
        
        return member != null ? convertToUserVO(member) : null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addGroupMember(String groupId, String userId, Integer role, String operatorId) {
        // 检查是否已是成员
        if (checkIsMember(groupId, userId)) {
            throw new BusinessException("用户已是群组成员");
        }
        
        ChatGroupMember member = new ChatGroupMember();
        member.setGroupId(groupId);
        member.setUserId(userId);
        member.setUserName("用户" + userId); // 实际应该从用户服务获取
        member.setRole(role != null ? role : 3); // 默认普通成员
        member.setStatus(1);
        member.setJoinTime(LocalDateTime.now());
        member.setCreateBy(operatorId);
        
        boolean result = save(member);
        
        if (result) {
            log.info("用户 {} 被 {} 添加到群组 {}", userId, operatorId, groupId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchAddGroupMembers(String groupId, List<String> userIds, String operatorId) {
        if (CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        
        List<ChatGroupMember> members = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        
        for (String userId : userIds) {
            if (!checkIsMember(groupId, userId)) {
                ChatGroupMember member = new ChatGroupMember();
                member.setGroupId(groupId);
                member.setUserId(userId);
                member.setUserName("用户" + userId);
                member.setRole(3); // 普通成员
                member.setStatus(1);
                member.setJoinTime(now);
                member.setCreateBy(operatorId);
                
                members.add(member);
            }
        }
        
        if (!CollectionUtils.isEmpty(members)) {
            boolean result = saveBatch(members);
            log.info("批量添加 {} 个成员到群组 {}", members.size(), groupId);
            return result;
        }
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeGroupMember(String groupId, String userId, String operatorId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember member = getOne(wrapper);
        if (member == null) {
            throw new BusinessException("用户不是群组成员");
        }
        
        // 检查权限：不能移除群主
        if (member.getRole() == 1) {
            throw new BusinessException("不能移除群主");
        }
        
        boolean result = removeById(member.getId());
        
        if (result) {
            log.info("用户 {} 被 {} 从群组 {} 移除", userId, operatorId, groupId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchRemoveGroupMembers(String groupId, List<String> userIds, String operatorId) {
        if (CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .in(ChatGroupMember::getUserId, userIds)
               .ne(ChatGroupMember::getRole, 1) // 不能移除群主
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        boolean result = remove(wrapper);
        
        if (result) {
            log.info("批量从群组 {} 移除成员", groupId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setMemberRole(String groupId, String userId, Integer role, String operatorId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember member = getOne(wrapper);
        if (member == null) {
            throw new BusinessException("用户不是群组成员");
        }
        
        member.setRole(role);
        member.setUpdateBy(operatorId);
        member.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(member);
        
        if (result) {
            log.info("用户 {} 在群组 {} 的角色被设置为 {}", userId, groupId, role);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchSetMemberRole(String groupId, List<String> userIds, Integer role, String operatorId) {
        if (CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .in(ChatGroupMember::getUserId, userIds)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        List<ChatGroupMember> members = list(wrapper);
        
        if (!CollectionUtils.isEmpty(members)) {
            LocalDateTime now = LocalDateTime.now();
            members.forEach(member -> {
                member.setRole(role);
                member.setUpdateBy(operatorId);
                member.setUpdateTime(now);
            });
            
            boolean result = updateBatchById(members);
            log.info("批量设置群组 {} 成员角色为 {}", groupId, role);
            return result;
        }
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean muteMember(String groupId, String userId, Integer muteMinutes, String operatorId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember member = getOne(wrapper);
        if (member == null) {
            throw new BusinessException("用户不是群组成员");
        }
        
        member.setMuteEndTime(LocalDateTime.now().plusMinutes(muteMinutes));
        member.setUpdateBy(operatorId);
        member.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(member);
        
        if (result) {
            log.info("用户 {} 在群组 {} 被禁言 {} 分钟", userId, groupId, muteMinutes);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unmuteMember(String groupId, String userId, String operatorId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember member = getOne(wrapper);
        if (member == null) {
            throw new BusinessException("用户不是群组成员");
        }
        
        member.setMuteEndTime(null);
        member.setUpdateBy(operatorId);
        member.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(member);
        
        if (result) {
            log.info("用户 {} 在群组 {} 被解除禁言", userId, groupId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchMuteMembers(String groupId, List<String> userIds, Integer muteMinutes, String operatorId) {
        if (CollectionUtils.isEmpty(userIds)) {
            return false;
        }
        
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .in(ChatGroupMember::getUserId, userIds)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        List<ChatGroupMember> members = list(wrapper);
        
        if (!CollectionUtils.isEmpty(members)) {
            LocalDateTime muteEndTime = LocalDateTime.now().plusMinutes(muteMinutes);
            LocalDateTime now = LocalDateTime.now();
            
            members.forEach(member -> {
                member.setMuteEndTime(muteEndTime);
                member.setUpdateBy(operatorId);
                member.setUpdateTime(now);
            });
            
            boolean result = updateBatchById(members);
            log.info("批量禁言群组 {} 成员 {} 分钟", groupId, muteMinutes);
            return result;
        }
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean transferOwnership(String groupId, String newOwnerId, String currentOwnerId) {
        // 检查当前群主
        LambdaQueryWrapper<ChatGroupMember> ownerWrapper = new LambdaQueryWrapper<>();
        ownerWrapper.eq(ChatGroupMember::getGroupId, groupId)
                   .eq(ChatGroupMember::getUserId, currentOwnerId)
                   .eq(ChatGroupMember::getRole, 1)
                   .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember currentOwner = getOne(ownerWrapper);
        if (currentOwner == null) {
            throw new BusinessException("当前用户不是群主");
        }
        
        // 检查新群主是否为成员
        LambdaQueryWrapper<ChatGroupMember> newOwnerWrapper = new LambdaQueryWrapper<>();
        newOwnerWrapper.eq(ChatGroupMember::getGroupId, groupId)
                      .eq(ChatGroupMember::getUserId, newOwnerId)
                      .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember newOwner = getOne(newOwnerWrapper);
        if (newOwner == null) {
            throw new BusinessException("新群主不是群组成员");
        }
        
        // 转让群主
        LocalDateTime now = LocalDateTime.now();
        
        currentOwner.setRole(2); // 降为管理员
        currentOwner.setUpdateTime(now);
        
        newOwner.setRole(1); // 升为群主
        newOwner.setUpdateTime(now);
        
        boolean result = updateBatchById(List.of(currentOwner, newOwner));
        
        if (result) {
            log.info("群组 {} 群主从 {} 转让给 {}", groupId, currentOwnerId, newOwnerId);
        }
        
        return result;
    }

    @Override
    public Boolean checkIsMember(String groupId, String userId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getStatus, 1)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        return count(wrapper) > 0;
    }

    @Override
    public Boolean checkIsAdmin(String groupId, String userId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getStatus, 1)
               .in(ChatGroupMember::getRole, 1, 2) // 群主或管理员
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        return count(wrapper) > 0;
    }

    @Override
    public Boolean checkUserPermission(String groupId, String userId, Integer requiredRole) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getStatus, 1)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember member = getOne(wrapper);
        if (member == null) {
            return false;
        }
        
        // 角色权限检查：1-群主 > 2-管理员 > 3-普通成员
        return member.getRole() <= requiredRole;
    }

    @Override
    public Integer countGroupMembers(String groupId, Integer status) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(status != null, ChatGroupMember::getStatus, status)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        return Math.toIntExact(count(wrapper));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateLastActiveTime(String groupId, String userId) {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatGroupMember::getGroupId, groupId)
               .eq(ChatGroupMember::getUserId, userId)
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        ChatGroupMember member = getOne(wrapper);
        if (member != null) {
            member.setLastActiveTime(LocalDateTime.now());
            return updateById(member);
        }
        
        return false;
    }

    @Override
    public List<ChatGroupMember> getExpiredMutedMembers() {
        LambdaQueryWrapper<ChatGroupMember> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNotNull(ChatGroupMember::getMuteEndTime)
               .lt(ChatGroupMember::getMuteEndTime, LocalDateTime.now())
               .eq(ChatGroupMember::getIsDeleted, 0);
        
        return list(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer autoUnmuteExpiredMembers() {
        List<ChatGroupMember> expiredMembers = getExpiredMutedMembers();
        
        if (!CollectionUtils.isEmpty(expiredMembers)) {
            expiredMembers.forEach(member -> member.setMuteEndTime(null));
            updateBatchById(expiredMembers);
            
            log.info("自动解除 {} 个过期禁言成员", expiredMembers.size());
            return expiredMembers.size();
        }
        
        return 0;
    }

    /**
     * 转换为用户VO对象
     */
    private ChatUserVO convertToUserVO(ChatGroupMember member) {
        ChatUserVO vo = new ChatUserVO();
        vo.setId(member.getUserId());
        vo.setName(member.getUserName());
        vo.setAvatar(member.getUserAvatar());
        vo.setRole(member.getRole());
        vo.setStatus(member.getStatus());
        vo.setJoinTime(member.getJoinTime());
        vo.setLastActiveTime(member.getLastActiveTime());
        vo.setMuteEndTime(member.getMuteEndTime());
        
        // 设置角色文本
        switch (member.getRole()) {
            case 1:
                vo.setRoleText("群主");
                break;
            case 2:
                vo.setRoleText("管理员");
                break;
            case 3:
                vo.setRoleText("成员");
                break;
            default:
                vo.setRoleText("未知");
        }
        
        // 设置是否被禁言
        vo.setIsMuted(member.getMuteEndTime() != null && 
                     member.getMuteEndTime().isAfter(LocalDateTime.now()));
        
        return vo;
    }
}
